package org.refresh.tests;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.refresh.core.RefreshMatrixCore;
import org.refresh.core.expr.BinaryExpression;
import org.refresh.core.expr.ConstantIntegerExpression;
import org.refresh.core.expr.SourceVariableSumExpression;
import org.refresh.core.expr.TargetVariableSumExpression;
import org.refresh.core.expr.TargetVariableValueExpression;

import junit.framework.TestCase;

/******************************************************************************
 * Copyright (c) 2005, 2006 Jules White.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Jules White - initial API and implementation 
 ****************************************************************************/
public class RefreshCoreTest extends TestCase {

	public void testMapAllNoConstraints(){
		RefreshMatrixCore core = new RefreshMatrixCore();
		core.setSetsToMap(new String[]{"a","b","c"}, new String[]{"1","2","3"});
		core.requireAllMappedExactlyOnce();
		Map<Object,List> sol = core.nextMapping();
		
		checkAllDeployed(sol);
	}
	
	public void testMapAllDifferentTargets(){
		RefreshMatrixCore core = new RefreshMatrixCore();
		core.setSetsToMap(new String[]{"a","b","c"}, new String[]{"1","2","3"});
		core.requireAllMappedExactlyOnce();
		core.addTargetMappedSourcesConstraint("1", 1);
		core.addTargetMappedSourcesConstraint("2", 1);
		core.addTargetMappedSourcesConstraint("3", 1);
		Map<Object,List> sol = core.nextMapping();
		
		ArrayList seen = new ArrayList();
		for(Object o : sol.keySet()){
			assertEquals(1, sol.get(o).size());
			assertTrue(!seen.contains(sol.get(o)));
			seen.add(sol.get(o));
		}
	}
	
	public void testBareResourceConstraints(){
		RefreshMatrixCore core = new RefreshMatrixCore();
		core.setSetsToMap(new String[]{"a","b","c"}, new String[]{"1","2","3"});
		core.setSourceVariableValues("a", new Object[]{"RAM",11});
		core.setSourceVariableValues("b", new Object[]{"RAM",9});
		core.setSourceVariableValues("c", new Object[]{"RAM",15});
		core.addTargetIntResourceConstraint("1", "RAM", 10);
		core.addTargetIntResourceConstraint("2", "RAM", 16);
		core.addTargetIntResourceConstraint("3", "RAM", 12);
		core.requireAllMappedExactlyOnce();
		Map sol = core.nextMapping();
		checkAllDeployed(sol);	
		assertEquals("3", ((List)sol.get("a")).get(0));
		assertEquals("1", ((List)sol.get("b")).get(0));
		assertEquals("2", ((List)sol.get("c")).get(0));
	}
	
	public void testMapWithRequiresAndExclusion(){
		RefreshMatrixCore core = new RefreshMatrixCore();
		core.setSetsToMap(new String[]{"a","b","c"}, new String[]{"1","2","3"});
		core.requireAllMappedExactlyOnce();
		core.addRequiresMappingConstraint("a", "b");
		core.addExcludesMappingConstraint("b", "c");
		Map<Object,List> sol = core.nextMapping();
		checkAllDeployed(sol);	
		assertTrue(!sol.get("a").equals(sol.get("c")));
		assertTrue(sol.get("a").equals(sol.get("b")));
	}
	
	public void testAutomotiveExampleFromDSALPaper(){
		long time = System.currentTimeMillis();
		RefreshMatrixCore core = new RefreshMatrixCore();
		core.setSetsToMap(new String[]{"ABS","BrakeActuators","SteeringControl","Infotainment","GPSNav"}, new String[]{"ECU1","ECU2","ECU3"});
		
		core.setSourceVariableValues("ABS", new Object[]{"RAM",1});
		core.setSourceVariableValues("BrakeActuators", new Object[]{"RAM",10});
		core.setSourceVariableValues("SteeringControl", new Object[]{"RAM",0});
		core.setSourceVariableValues("Infotainment", new Object[]{"RAM",3});
		core.setSourceVariableValues("GPSNav", new Object[]{"RAM",5});
		
		core.setTargetVariableValues("ECU1", new Object[]{"Cost",10,"FirmwareVendor",1,"FirmwareVersion",15});
		core.setTargetVariableValues("ECU2", new Object[]{"Cost",16,"FirmwareVendor",1,"FirmwareVersion",19});
		core.setTargetVariableValues("ECU3", new Object[]{"Cost",19,"FirmwareVendor",1,"FirmwareVersion",19});
		
		core.addExcludesMappingConstraint("ABS", "SteeringControl");
		core.addRequiresMappingConstraint("ABS", "BrakeActuators");
		
		TargetVariableValueExpression tve = new TargetVariableValueExpression("FirmwareVersion");
		BinaryExpression be = new BinaryExpression(tve,new ConstantIntegerExpression(12),">");
		core.addSourceMappingConstraint("BrakeActuators", be);
		
		tve = new TargetVariableValueExpression("FirmwareVendor");
		be = new BinaryExpression(tve,new ConstantIntegerExpression(1),"=");
		core.addSourceMappingConstraint("BrakeActuators", be);
		
		tve = new TargetVariableValueExpression("FirmwareVersion");
		be = new BinaryExpression(tve,new ConstantIntegerExpression(16),">");
		core.addSourceMappingConstraint("SteeringControl", be);
		
		core.addTargetIntResourceConstraint("ECU1", "RAM", 9);
		core.addTargetIntResourceConstraint("ECU2", "RAM", 12);
		core.addTargetIntResourceConstraint("ECU3", "RAM", 15);
		

		core.requireAllMappedExactlyOnce();
		
		core.setOptimizationFunction(new TargetVariableSumExpression("Cost"));
		core.setMaximizeOptimizationFunction(false);
		Map sol = core.nextMapping();
		long finish = System.currentTimeMillis();
		//System.out.println(finish-time);
		checkAllDeployed(sol);	
		
	}
	
	public List generateNItemSet(String prefix, int items){
		ArrayList set = new ArrayList(items);
		for(int i = 0; i < items; i++){
			set.add(prefix+i);
		}
		return set;
	}
	
//	public void testTimeLimitSolving(){
//		int tsrc = 1000;
//		int ttrg = 10;
//		List srcs = generateNItemSet("src_", tsrc);
//		List trgs = generateNItemSet("trg_", ttrg);
//		RefreshCore core = new RefreshCore();
//		core.setSetsToMap(srcs, trgs);
//		
//		
//		for(int i = 0; i < tsrc; i++){
//			core.setSourceVariableValues("src_"+i, new Object[]{"RAM",i+1});
//		}
//		for(int i = 0; i < ttrg; i++){
//			core.addTargetIntResourceConstraint("trg_"+i, "RAM", 1000);
//		}
//		long start = System.currentTimeMillis();
//		core.nextMappingWithinTimeLimit(100);
//		long end = System.currentTimeMillis();
//		
//	}
	
	public void testLargeAssignment(){
//		int tsrc = 200;
//		int ttrg = 5;
//		List srcs = generateNItemSet("src_", tsrc);
//		List trgs = generateNItemSet("trg_", ttrg);
//		RefreshMatrixCore core = new RefreshMatrixCore();
//		//core.setSetsToMap(srcs, trgs);
//		
//		int[] cvalues = new int[tsrc];
//		for(int i = 0; i < tsrc; i++){
//			cvalues[i] = i;
//		}
//		int[] vals = new int[ttrg];
//		for(int i = 0; i < ttrg; i++){
//			//core.addTargetIntResourceConstraint("trg_"+i, "RAM", 1000);
//			vals[i] = 20000;
//		}
//		long start = System.currentTimeMillis();
//		core.testScheduling();
//		//core.nextMappingWithResourceValues2("RAM", vals, cvalues);
//		long end = System.currentTimeMillis();
//		System.out.println("Scheduling Based:"+(end-start));
//		
//		RefreshMatrixCore core2 = new RefreshMatrixCore();
//		core2.setSetsToMap(srcs, trgs);
//		for(int i = 0; i < tsrc; i++){
//			core2.setSourceVariableValues("src_"+i, new Object[]{"RAM",i+1});
//		}
//		for(int i = 0; i < ttrg; i++){
//			core2.addTargetIntResourceConstraint(trgs.get(i), "RAM", 1000);
//		}
//		core2.requireAllMappedExactlyOnce();
//		start = System.currentTimeMillis();
//		core2.nextMapping();
//		end = System.currentTimeMillis();
//		System.out.println("Matrix Based:"+(end-start));
	}
	
	public void testSchedulingBasedResAssignment(){
//		long time = System.currentTimeMillis();
//		RefreshMatrixCore core = new RefreshMatrixCore();
//		core.setSetsToMap(new String[]{"ABS","BrakeActuators","SteeringControl","Infotainment","GPSNav"}, new String[]{"ECU1","ECU2","ECU3"});
//		
//		core.setSourceVariableValues("ABS", new Object[]{"RAM",1});
//		core.setSourceVariableValues("BrakeActuators", new Object[]{"RAM",10});
//		core.setSourceVariableValues("SteeringControl", new Object[]{"RAM",0});
//		core.setSourceVariableValues("Infotainment", new Object[]{"RAM",3});
//		core.setSourceVariableValues("GPSNav", new Object[]{"RAM",5});
//		
//		core.setTargetVariableValues("ECU1", new Object[]{"Cost",10,"FirmwareVendor",1,"FirmwareVersion",15});
//		core.setTargetVariableValues("ECU2", new Object[]{"Cost",16,"FirmwareVendor",1,"FirmwareVersion",19});
//		core.setTargetVariableValues("ECU3", new Object[]{"Cost",19,"FirmwareVendor",1,"FirmwareVersion",19});
//		
//		core.addExcludesMappingConstraint("ABS", "SteeringControl");
//		core.addRequiresMappingConstraint("ABS", "BrakeActuators");
//		
//		core.requireAllMappedExactlyOnce();
//		
		//core.nextMappingWithResourceValues("RAM", new int[]{9,12,15});
	}
	
	
	public void testAutomotiveExampleFromDSALPaperOptFreeMem(){
		long time = System.currentTimeMillis();
		RefreshMatrixCore core = new RefreshMatrixCore();
		core.setSetsToMap(new String[]{"ABS","BrakeActuators","SteeringControl","Infotainment","GPSNav"}, new String[]{"ECU1","ECU2","ECU3"});
		
		core.setSourceVariableValues("ABS", new Object[]{"RAM",1});
		core.setSourceVariableValues("BrakeActuators", new Object[]{"RAM",10});
		core.setSourceVariableValues("SteeringControl", new Object[]{"RAM",0});
		core.setSourceVariableValues("Infotainment", new Object[]{"RAM",3});
		core.setSourceVariableValues("GPSNav", new Object[]{"RAM",5});
		
		core.setTargetVariableValues("ECU1", new Object[]{"Cost",10,"FirmwareVendor",1,"FirmwareVersion",15});
		core.setTargetVariableValues("ECU2", new Object[]{"Cost",16,"FirmwareVendor",1,"FirmwareVersion",19});
		core.setTargetVariableValues("ECU3", new Object[]{"Cost",19,"FirmwareVendor",1,"FirmwareVersion",19});
		
		core.addExcludesMappingConstraint("ABS", "SteeringControl");
		core.addRequiresMappingConstraint("ABS", "BrakeActuators");
		
		TargetVariableValueExpression tve = new TargetVariableValueExpression("FirmwareVersion");
		BinaryExpression be = new BinaryExpression(tve,new ConstantIntegerExpression(12),">");
		core.addSourceMappingConstraint("BrakeActuators", be);
		
		tve = new TargetVariableValueExpression("FirmwareVendor");
		be = new BinaryExpression(tve,new ConstantIntegerExpression(1),"=");
		core.addSourceMappingConstraint("BrakeActuators", be);
		
		tve = new TargetVariableValueExpression("FirmwareVersion");
		be = new BinaryExpression(tve,new ConstantIntegerExpression(16),">");
		core.addSourceMappingConstraint("SteeringControl", be);
		
		core.addTargetIntResourceConstraint("ECU1", "RAM", 9);
		core.addTargetIntResourceConstraint("ECU2", "RAM", 12);
		core.addTargetIntResourceConstraint("ECU3", "RAM", 15);
		

		core.requireAllMappedExactlyOnce();
		
		core.setOptimizationFunction(new BinaryExpression(new TargetVariableSumExpression("RAM"),new SourceVariableSumExpression("RAM"),"-"));
		core.setMaximizeOptimizationFunction(true);
		Map sol = core.nextMapping();
		long finish = System.currentTimeMillis();
		//System.out.println(finish-time);
		checkAllDeployed(sol);	
		
	}
	
	public void checkAllDeployed(Map<Object,List> sol){
		for(Object o : sol.keySet()){
			assertEquals(1, sol.get(o).size());
		}
	}
}
